home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-10-31 | 14.0 KB | 597 lines | [TEXT/MSET] |
- \ Files - file object and loader
-
- cl1 \ In case we're reloading
- ' cl1 -> abortVec
- 0 -> quitvec
-
-
- 0 value SFDlgHook \ Used in std file calls. If non-zero,
- \ points to the proc to be called while
- \ the std file dialog is up.
-
- -39 constant EOF \ EOF error return
- -43 constant FNF \ File not found ditto
-
- -300 constant FILE-MARK
- \ Marks the start of a loaded file - we plant some useful info there.
- \ We put the file name in the dic as if it's a definition name, but use
- \ file-mark as a "handler code". Then after that we put the useful info.
- \ See extrasMod.
-
- false value ASYNCH?
- false value ENDLOAD?
- false value LOG?
-
- 0 value OPEN_CNT
- 0 value CLOSE_ERR_CNT
-
- forward CREATE_LOG
- forward WRITE_LOG
-
- string $LG1
- string $LG2
-
-
- : ASYNCH true -> asynch? ;
-
- : IOWAIT BEGIN busy 0EXIT pause AGAIN ;
-
- : (ASY) \ ( fcb -- ) Sets up for a low-level asynchronous read or write.
- IOwait
- -> busy setCP ;
-
-
- : VOLNAME? { str -- b }
- reset: str
- 58 chsearch: str
- NIF false EXIT THEN
- lim: str 2 >= ;
-
-
- forward OPEN_WITH_PATHS
-
- false value USE_PATHS?
-
- : HFS? $ 3f6 w@x 0> ;
-
- variable MyDocName 28 allot
-
- : MyDoc \ ( -- addr len )
- MyDocName count ;
-
-
- \ Standard file package support
-
- : SFLOC { \ ht wd -- x:y }
- \ Computes screen coordinates for top left of
- \ SF dialog box. Centers the box horizontally, and a bit above
- \ the center vertically.
- screenbits -> ht -> wd 2drop
- ht 3 / 80 - 0 max -> ht
- wd 2/ 170 - 0 max -> wd
- wd ht pack ;
-
-
- :class SFrec super{ object }
-
- record
- { int Good
- var fType
- int vRefNum
- int Version
- 64 bytes Filename \ max size is 64
- }
- 4 ordered-col fTypes \ list of filetypes
-
-
- :m GetVRefNum: get: vRefNum ;m
- :m GetName: addr: FileName ;m
-
- :m CALL: \ ( routine# -- bool ) Calls a Standard File Package routine.
- SFDlgHook ^base rot makeint trap$ A9EA
- get: good ;m
-
- :m STDGET: ( type0 ...typeN ) { #types -- bool }
- clear: fTypes #types 0>
- IF #types 0 DO add: fTypes LOOP THEN
- SFloc 0 0 #types makeint ixAddr: fTypes
- 2 call: self ;m
-
- :m STDPUT: { pAddr pLen nAddr nLen -- bool }
- pAddr pLen pad place
- SFloc pad nAddr nLen str255
- 1 call: self ;m
-
- ;class
-
-
- objHandle SFHDL
- objPtr SFOBJ class_is SFrec
-
-
- \ DO_OPEN does the hard work for OPEN: file. First, if either the DirID
- \ or the vol ref# is non-zero, we rashly assume we know which folder we
- \ want, and just do an open. We also do that if we're not running under HFS.
- \ Then, if we get through to here, we need to look at the paths. But wait!
- \ First, we check the default folder by just doing a plain open anyway! If
- \ this fails with a "file not found", we call ?USE_PATHS which either does
- \ nothing (if we're not using a path designator file), or calls our PATHSMOD
- \ module to look at a PD file and try using those paths to find the wanted
- \ file.
-
- : DO_OPEN { fcb mode -- rc }
- 1 ++> open_cnt
- ^base 48 + @ \ DirID
- ^base 22 + w@ \ vol ref#
- or HFS? not or \ Either non-zero, or not HFS?
- use_paths? not or \ Or paths disabled?
- IF \ Yes: just do a normal open, and get out.
- fcb mode (open) EXIT
- THEN
- \ Maybe use HFS paths:
- fcb mode (open) dup 0EXIT \ Try default folder first
- \ -- out if we found it
- dup FNF <> ?EXIT \ If err wasn't FNF, get out
- use_paths? 0EXIT \ If paths disabled, out with FNF
- drop fcb mode open_with_paths ;
-
-
- :class FILE super{ object } general
-
- 134 bytes FCB \ max parameter block (108 but for hgetvinfo)
-
- record FSSpec
- { int FSvRefNum
- var FSDirID
- 64 bytes FileName
- }
-
- :m CLEAR: \ Clears the fcb, except for the filename.
- ^base 18 erase ^base 22 + 112 erase ;m
-
- :m SETNAMEPTR: \ Sets filename pointer in the FCB.
- ^base 140 + ^base !fptr ;m
-
- :m NAME: \ ( addr len -- ) Assigns file name to fcb. Rest cleared.
- setNamePtr: self clear: self
- ^base 140 + >r \ Addr of filename (at end of fcb)
- r@ 64 blanks
- ( addr len ) 64 min r> >str255 drop ;m
-
- :m SETDIRID: \ ( dirid -- ) Sets the DirID for the fcb
- ^base 48 + ! ;m
-
- :m GETDIRID: \ ( -- dirid ) Gets the DirID for the fcb
- ^base 48 + @ ;m
-
- :m GETFREF: \ ( -- fref ) Gets the file ref number.
- ^base 24 + w@ ;m
-
- :m SETFREF:
- ^base 24 + w! ;m
-
- :m SETVREF: \ ( vref# -- ) Sets the volRefNum for the fcb
- ^base 22 + w! ;m
-
- :m GETVREF: \ ( -- vref# ) Gets the volRefNum for the fcb
- ^base 22 + w@ ;m
-
-
- :m CLOSE: \ ( -- rc ) Needs to clear the file RefNum field,
- \ as advised in Mac Tech note # 102. In fact we clear
- \ the whole fcb except the name and Vref, so we can reuse
- \ the fcb for a subsequent operation without the extra info
- \ left by read and write calls being interpreted as HFS info.
-
- ^base (close) getVref: self clear: self setVref: self
- dup if 1 ++> close_err_cnt else -1 ++> open_cnt then ;m
-
-
- :m OPEN: \ ( -- rc )
- ^base 0 do_open ;m
-
- :m OPENREADONLY:
- ^base 1 do_open ;m
-
-
- :m NEW: ^base (make) ;m
-
- :m DELETE: ^base (delete) ;m
-
- :m MOVETO: \ ( byteoffset -- rc ) Positions relative to start of file
- ^base 1 rot (lseek) ;m
-
- :m POS: \ ( -- byteoffset )
- ^base $ 2E + @ ;m
-
- :m SETEOF: \ ( pos -- rc ) Sets end-of-file to absolute byte position
- ^base 28 + ! ^base fdos$ a012 ;m
-
- :m CREATE: { \ volID -- }
- \ Opens and resets file or creates new if not present.
- 1 ++> open_cnt
- ^base 0 (open) \ Attempt to open - don't use paths
- ?dup
- IF dup FNF =
- IF drop
- new: self ?dup NIF ^base 0 (open) THEN
- THEN
- ELSE
- 0 setEOF: self
- THEN ;m
-
- :m LAST: \ Positions to end of file.
- big# moveto: self drop ;m
-
- :m SIZE: \ ( -- #bytes ) Returns logical eof for file currently open
- ^base fdos$ a011 drop ^base 28 + @ ;m
-
- :m BYTESREAD: \ ( -- n ) Returns actual bytes read.
- ^base 40 + @ ;m
-
- :m FCB: ( -- fcb ) ^base ;m
-
- :m RESULT: \ ( -- rc ) Returns the last I/O result code.
- ^base 16 + w@ ;m
-
- :m MODE: \ ( posMode -- ) Sets position mode
- ^base 44 + w! ;m
-
-
- :m WAIT: \ ( -- rc ) Waits for asynch I/O on this file to finish.
- BEGIN ^base busy =
- NIF ^base 16 + w@x EXIT THEN
- pause
- AGAIN ;m
-
- :m ?WAIT: \ ( rc1 -- rc2 )
- asynch?
- NIF drop wait: self
- ELSE false -> asynch?
- THEN ;m
-
-
- :m READ: \ ( addr length -- rc )
- 0 mode: self ^base swap rot
- ^base (asy) (read) ?wait: self ;m
-
- :m READLINE: \ ( addr maxLen -- rc ) Reads terminating with CR
- $ 0D80 mode: self ^base swap rot
- ^base (asy) (read) ?wait: self ;m
-
- :m WRITE: \ ( addr length -- rc )
- ^base swap rot
- ^base (asy) (write) ?wait: self ;m
-
- :m SETNAME: \ Gets name from input stream, and assigns to fcb.
- & " parse-word name: self ;m
-
- :m GETNAME: \ ( -- addr len ) Returns filename
- addr: fileName count ;m
-
- :m PRINT: \ Prints the filename.
- getName: self type ;m
-
- :m GETFILEINFO: \ ( -- rc ) Fills the parameter block with file info
- ^base fdos$ A20C ;m
-
- :m SETFILEINFO: \ ( -- rc )
- ^base fdos$ A20D ;m
-
- :m SET: { ftyp sig -- } \ Sets file type, signature.
- getDirID: self \ Save DirID
- 0 setDirID: self \ and clear it (otherwise we'll get
- getFileInfo: self drop \ "file not found")
- sig ^base $ 24 + ! \ Set signature
- ftyp ^base $ 20 + ! \ Set type
- 0 setDirID: self
- setFileInfo: self drop
- setDirID: self ;m \ Restore DirID
-
-
- :m DRIVE: \ ( drive# -- ) set default drive to drive#
- clear: self setVRef: self ^base fdos$ a015
- ?error 165 ;m
-
-
- :m ACCEPT: { addr len \ #chrs eof? -- #chrs eof? } \ ACCEPTs from disk.
- echo? IF addr len erase THEN \ So the typed line is OK
- addr len readLine: self -> eof?
- bytesRead: self eof? NIF 1- THEN -> #chrs
- #chrs 0= eof? and IF 0 true EXIT THEN
- addr #chrs + c@ 13 <>
- IF \ Overlength line. Probably a comment.
- BEGIN \ Gobble to CR or EOF
- pad 100 readLine: self -> eof?
- eof?
- IF true
- ELSE pad bytesRead: self 1- + c@ 13 =
- THEN
- UNTIL
- THEN
- #chrs -> len
- echo?
- IF addr len type cr THEN
- BEGIN \ Loop to convert tabs to blanks
- addr len 9 scan -> len -> addr
- len
- WHILE
- bl addr c!
- REPEAT
- #chrs false ;m
-
-
- :m RENAME: { taddr tlen -- rc }
- taddr tlen str255
- ^base 28 + ! ^base fdos$ A00B ;m
-
-
- :m GETTYPE: \ ( -- type )
- ^base 32 + @ ;m
-
- :m FLUSHVOL:
- ^base fdos$ A013 drop ;m
-
-
- :m CLASSINIT: clear: self setNamePtr: self ;m
-
-
- \ Standard file package calls. If the value SFDlgHook is non-zero, we take it as the
- \ address of a dialog hook routine.
-
- private
-
- :m SFPCALL: \ ( various get? -- b ) Calls a Standard File Package routine
- classinit: self \ Make sure name pointer is right
- ['] SFrec newObj: SFhdl
- obj: SFhdl -> SFobj
- IF stdGet: SFobj ELSE stdPut: SFobj THEN
- IF getVRefNum: SFobj clear: self setVref: self
- getName: SFobj count addr: fileName place
- true
- ELSE
- false
- THEN
- release: SFhdl ;m
-
- public
-
- :m STDGET: \ ( type0 ...typeN #types -- bool )
- true sfpCall: self ;m
-
- :m STDPUT: \ ( pAddr pLen nAddr nLen -- bool )
- false sfpCall: self ;m
-
- ;class
-
-
- ' fFcb set_to_class file \ Make fFcb a FILE objPtr
- 6 fFcb 8 - w!
- ' file fFcb 6 - reloc!
- -6 fFcb 2 - w!
-
-
- \ GetDirID returns the dirID of the last directory opened by a
- \ standard file call.
-
- : GETDIRID $ 398 @ ;
-
-
- \ FileList keeps a stack of open load files for nested loads.
-
- objPtr TOPFILE class_is file
-
-
- :class FILELIST super{ handleArray }
-
- :m DROP:
- top: super \ Give error if empty
- close: topFile drop
- drop: super
- size: super NIF nilP ELSE obj: self THEN
- -> topFile
- false -> endload? ;m
-
- :m PUSHNEW: \ Adds a new file to the stack
- ['] file pushNewObj: self
- false -> endload?
- obj: self -> topFile \ Note this locks the file object
- \ -- this is what we want.
- 0 setVref: topFile ;m
-
- :m CLEAR: \ Removes all currently open files
- false -> endload?
- get: size 0EXIT
- type# 180 ( File stack: ) cr top: self
- get: size FOR
- print: topFile cr drop: self
- NEXT ;m
-
- ;class
-
-
- 10 fileList LOADFILE
-
- 0 value FILESTART_DP
- 0 value CNT
- 0 value SvLATEST
-
-
- : LOGIT
- state 0EXIT \ Out if we're not compiling
- here filestart_DP - pad w!
- pos: topFile src-len -
- pad 2+ !
- pad 6 add: $lg1 ;
-
-
- 0 value LASTPOS
-
- : LOGCR
- state 0EXIT
- here lastPos <= ?EXIT
- here -> lastPos
- pad 14 erase
- here filestart_DP - pad w!
- latest svLatest <> IF true pad 4+ c! latest -> svLatest THEN
- pad 14 add: $lg2 ;
-
-
- : (FREFILL) \ ( -- flag ) Does a refill from a file.
- echo?
- IF ?pause
- ELSE cnt NIF ?pause 20 -> cnt else 1 --> cnt THEN
- THEN
- log? IF logCR THEN
- tib tibLen accept: topfile ( #chrs eof? ) -> endload? #tib !
- set_source endload? 0= ;
-
- ' (Frefill) -> Frefill
-
-
- : (LD)
- BEGIN
- endload? IF false -> endload? EXIT THEN
- topfile -> source-ID (Frefill) IF interpret THEN
- state not echo? and fWind? and IF ok THEN
- AGAIN ;
-
-
- false value DO_CR?
-
- : LOADTOP { \ svCurs svHere svDepth -- }
- \ Interprets the file as a Mops source file.
- openReadOnly: topfile
- IF ( error ) getName: topfile type 132 die THEN
- curs -> svCurs -curs
- cr
- size: loadFile 2* spaces type# 173 ( Loading: )
- getName: topfile type
- log? IF
- create_log ['] logit -> logVec
- 0 -> svLatest
- THEN
- here -> svHere depth -> svDepth
- false -> endload? false -> do_cr?
- (ld)
- ['] null -> logvec
- close: topfile drop log? IF write_log THEN
- do_cr?
- IF cr size: loadFile 2* ELSE 2 THEN spaces true -> do_cr?
- here svHere - ." Size: " .
- size: loadFile 1 <= IF cr THEN
- depth svDepth <> IF cr msg# 75 THEN
- \ Warning - stack depth different after load
- svCurs -> curs ;
-
-
- : ENDLOAD true -> endload? 0 -> src-len ;
-
-
- \ Nesting loader. Usage: // filename
-
- : // { \ svcurs addr len -- }
- pushNew: loadFile setName: topFile
- getName: topFile mark_file
- loadTop
- drop: loadFile ;
-
-
- \ ======= Module support ========
-
- : NOMOD -1 -> modbase -1 -> MBcomp 0 -> CompMod ;
-
-
- : LDFROMMOD { newModbase \ svModbase svMBcomp -- }
- \ Load from a module. We save and restore the current
- \ modbase and MBcomp value, in case the load changes them.
-
- modbase -> svModbase MBcomp -> svMBcomp
- newModbase dup -> modbase -> MBcomp
- loadtop
- svModbase -> modbase svMBcomp -> MBcomp ;
-
-
- \ ========== Save ==========
-
- 'type COM constant SAVETYPE \ file type = 'COM '
- 'type MOPS constant SAVESIG \ Signature = 'MOPS'
-
- : SAVE_THIS \ ( -- addr len ) Defines what to save
- ['] latest here over - ;
-
-
- \ PURGE gets rid of all loaded modules. It is defined in the file Modules.
- \ SAVE needs to call it first, so that saved dic images don't appear to
- \ reference loaded modules which aren't really loaded. So that we can call
- \ SAVE before Modules is loaded, we make PURGE a vector rather than a
- \ forward definition.
-
- ' null vect PURGE
-
-
- : (SAVE) { \ savdp savlatest -- rc }
- create: ffcb ?error 107
- dp -> savdp latest -> savlatest
- save_this \ Call before we clobber DP
- dp ['] dp - -> dp \ Here we make DP and LATEST relative
- latest ['] dp - -> latest \ to DP so we can set them up when
- \ saved image is read in
- purge \ Purge modules so saved image has them all
- \ unloaded
- true -> savingDic? \ Stops PAUSE from doing anything during
- \ asynch I/O (could try to call a module,
- \ but they're purged)
- write: ffcb \ Leave return code on stack for caller
- false -> savingDic?
- savdp -> dp savlatest -> latest \ and DP and LATEST
- savetype savesig set: ffcb
- close: ffcb drop
- \ type# 101 ( Saved: ) getname: ffcb type cr ;
- ;
-
- : SAVE \ Takes name from input stream. Redefined later in Frontend.
- setname: ffcb (save) ?error 105 ;
-
-
- \ CL2 is the next cleanup word - it cleans up all file stuff on abort,
- \ as well as whatever we were doing before (see CL1 in file Class).
-
- : CL2
- clear: loadfile close: ffcb drop
- nomod release: $lg1 release: $lg2
- ['] null -> logvec false -> endload?
- false -> savingDic?
- cl1 ;
-
-
- : FILINIT
- ['] file dup ['] fFcb 4+ reloc!
- fFcb 18 + @ \ Name pointer - doc name may not be in fFcb
- count 32 min myDocName place
- fFcb make_obj
- clear: loadfile ;
-
-
- ' filinit -> objinit
- ' cl2 -> abortvec
-
- ' -echo ' +echo \ used when we execute x below
-
- : -ECHO false -> echo? ;
- : +ECHO true -> echo? ;
-
- : x
- execute \ old +echo
- -curs
- ." saving interim.dic. Now type" cr
- ." // sys.ld" cr
- ." to load the rest of the system."
- execute \ old -echo
- +curs
- ;
-
-
- x forget x
- save interim.dic
-